﻿#include "Input.h"

Input::Input()
{
  std::fill(m_keys, m_keys + GLFW_KEY_LAST, false);
  std::fill(m_keysPrevious, m_keysPrevious + GLFW_KEY_LAST, false);
  std::fill(m_mouseButtons, m_mouseButtons + GLFW_MOUSE_BUTTON_LAST, false);
  std::fill(m_mouseButtonsPrevious, m_mouseButtonsPrevious + GLFW_MOUSE_BUTTON_LAST, false);
}

void Input::InitCallbacks(const Ref<Window> &window)
{
  auto &dispatcher = window->GetDispatcher();

  dispatcher.Subscribe(
      EventType::KeyPressed,
      [&](Event &event)
      {
        auto &keyEvent = static_cast<KeyPressedEvent &>(event);
        SetKeyState(keyEvent.GetKey(), true);
      });

  dispatcher.Subscribe(
      EventType::KeyReleased,
      [&](Event &event)
      {
        auto &keyEvent = static_cast<KeyReleasedEvent &>(event);
        SetKeyState(keyEvent.GetKey(), false);
      });

  dispatcher.Subscribe(
      EventType::MouseButtonPressed,
      [&](Event &event)
      {
        auto &mouseEvent = static_cast<MouseButtonPressedEvent &>(event);
        SetMouseButtonState(mouseEvent.GetButton(), true);
      });

  dispatcher.Subscribe(
      EventType::MouseButtonReleased,
      [&](Event &event)
      {
        auto &mouseEvent = static_cast<MouseButtonReleasedEvent &>(event);
        SetMouseButtonState(mouseEvent.GetButton(), false);
      });

  dispatcher.Subscribe(
      EventType::MouseMoved,
      [&](Event &event)
      {
        auto &mouseEvent = static_cast<MouseMovedEvent &>(event);
        SetMousePosition(mouseEvent.GetPosition());
      });
}

bool Input::IsKeyJustPressed(int keyCode)
{
  return m_keys[keyCode] && !m_keysPrevious[keyCode];
}

bool Input::IsKeyPressing(int keyCode)
{
  return m_keys[keyCode] && m_keysPrevious[keyCode];
}

bool Input::IsKeyJustReleased(int keyCode)
{
  return !m_keys[keyCode] && m_keysPrevious[keyCode];
}

bool Input::IsMouseButtonJustPressed(int button)
{
  return m_mouseButtons[button] && !m_mouseButtonsPrevious[button];
}

bool Input::IsMouseButtonPressing(int button)
{
  return m_mouseButtons[button] && m_mouseButtonsPrevious[button];
}

glm::vec2 Input::GetMousePosition() 
{ 
  return m_mousePos; 
  }

glm::vec2 Input::GetMousePositionDelta()
{
  return m_mousePosDelta;
}

void Input::SetKeyState(int keyCode, bool pressed)
{
  m_keysPrevious[keyCode] = m_keys[keyCode];
  m_keys[keyCode] = pressed;
}

void Input::SetMouseButtonState(int button, bool pressed)
{
  m_mouseButtonsPrevious[button] = m_mouseButtons[button];
  m_mouseButtons[button] = pressed;
}

void Input::SetMousePosition(const glm::vec2 &pos) 
{ 
  m_mousePosDelta = m_mousePos - pos;
  m_mousePos = pos; 
}

void Input::NextFrame()
{
  for (int i = 0; i < GLFW_MOUSE_BUTTON_LAST; i++)
  {
    m_mouseButtonsPrevious[i] = m_mouseButtons[i];
  }
  for (int i = 0; i < GLFW_KEY_LAST; i++)
  {
    m_keysPrevious[i] = m_keys[i];
  }
  m_mousePosDelta = {0, 0};
}